package com.lqw.wechat.service.wechatservice.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lqw.wechat.common.config.WeChatAccessConfig;
import com.lqw.wechat.common.config.WeChatRequestConfig;
import com.lqw.wechat.common.constants.WeChatEventTypeCons;
import com.lqw.wechat.common.constants.WeChatMessageXmlKeyCons;
import com.lqw.wechat.common.constants.WeChatMsgTypeValuesCons;
import com.lqw.wechat.common.response.message.TextMessageResponse;
import com.lqw.wechat.common.util.HttpUtil;
import com.lqw.wechat.common.util.WeChatUtil;
import com.lqw.wechat.common.vo.BaseUserInfo;
import com.lqw.wechat.common.vo.WeChatAccessToken;
import com.lqw.wechat.entity.ReplyMessage;
import com.lqw.wechat.service.follower.FollowerService;
import com.lqw.wechat.service.wechatservice.WeChatService;
import com.lqw.wechat.service.replymessage.ReplyMessageService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by luqiwen on 2017/7/26.
 * 微信入口处理 service 实现类
 */
@Service
public class WeChatServiceImpl implements WeChatService{

    private static final Logger LOGGER= LoggerFactory.getLogger(WeChatServiceImpl.class);

    @Autowired
    private WeChatAccessConfig weChatAccessConfig;


    @Autowired
    private WeChatRequestConfig weChatRequestConfig;

    @Autowired
    private ReplyMessageService replyMessageService;

    @Autowired
    private FollowerService followerService;

    private static final String ACCESS_TOKEN_KEY="lqw_wechat_access_token_key";
    private static final String DEFAULT_APP_ID_KEY = "appid";
    private static final String DEFAULT_SECRET_KEY = "secret";
    private static final Map<String, WeChatAccessToken> ACCESS_TOKEN_MAP = new ConcurrentHashMap<>();

    @Override
    public String process(Map<String, String> paramMap) {
        String msgType=paramMap.get(WeChatMessageXmlKeyCons.MSG_TYPE);
        List<String> list=getServiceIps();
        LOGGER.info("服务器IP地址个数:{}",list.size());
        if(WeChatMsgTypeValuesCons.EVENT.equals(msgType)){
            // 事件类型消息
            String event=paramMap.get(WeChatMessageXmlKeyCons.EVENT);
            if(WeChatEventTypeCons.SUBSCRIBE.equals(event)
                    || WeChatEventTypeCons.SCAN.equals(event)){
                // 用户关注，保存用户 openId
                followerService.subscribe(paramMap.get(WeChatMessageXmlKeyCons.FORM_USER_NAME),Long.parseLong(paramMap.get(WeChatMessageXmlKeyCons.CREATE_TIME)));

                BaseUserInfo baseUserInfo=getBaseUserInfo(paramMap.get(WeChatMessageXmlKeyCons.FORM_USER_NAME));
                LOGGER.info(baseUserInfo.getNickname());
                // 保存成功，向用户发送消息
                ReplyMessage replyMessage=replyMessageService.getMessageByEvent(event);
                if(replyMessage==null){
                    return null;
                }
                TextMessageResponse text=new TextMessageResponse();
                text.setContent(replyMessage.getMessage());
                text.setCreateTime(System.currentTimeMillis());
                text.setMsgType(WeChatMsgTypeValuesCons.TEXT);
                text.setFromUserName(paramMap.get(WeChatMessageXmlKeyCons.TO_USER_NAME));
                text.setToUserName(paramMap.get(WeChatMessageXmlKeyCons.FORM_USER_NAME));
                return WeChatUtil.bean2Xml(text, TextMessageResponse.class);
            }else if(WeChatEventTypeCons.UN_SUBSCRIBE.equals(event)){
                followerService.unSubscribe(paramMap.get(WeChatMessageXmlKeyCons.FORM_USER_NAME));
            }
        } else if(WeChatMsgTypeValuesCons.TEXT.equals(msgType)){
            // 用户发消息过来
            TextMessageResponse text=new TextMessageResponse();
            ReplyMessage replyMessage=replyMessageService.getMessageByKeyWord(paramMap.get(WeChatMessageXmlKeyCons.CONTENT),msgType);
            if(replyMessage==null){
                text.setMsgType(WeChatMsgTypeValuesCons.TRANSFER_CUSTOMER_SERVICE);
            }else{
                text.setContent(replyMessage.getMessage());
                text.setMsgType(msgType);
            }
            text.setCreateTime(System.currentTimeMillis());
            text.setFromUserName(paramMap.get(WeChatMessageXmlKeyCons.TO_USER_NAME));
            text.setToUserName(paramMap.get(WeChatMessageXmlKeyCons.FORM_USER_NAME));
            return WeChatUtil.bean2Xml(text, TextMessageResponse.class);
        }

        return null;
    }

    public List<String> getServiceIps(){
        Map<String,Object> params=new HashMap<>();
        params.put("access_token", getAccessToken());
        String result= HttpUtil.sendGet(weChatRequestConfig.getServiceIpsUrl(), params);
        List<String> lists=(List<String>)JSON.parseObject(result).get("ip_list");
        return lists;
    }

    public BaseUserInfo getBaseUserInfo(String openId){
        if(StringUtils.isEmpty(openId)){
            LOGGER.info("用户基本信息失败，openId不能为空");
            return null;
        }
        Map<String,Object> params=new HashMap<>();
        params.put("access_token", getAccessToken());
        params.put("openid", weChatAccessConfig.getAppId());
        params.put("lang","zh_CN");
        String resultJson=HttpUtil.sendGet(weChatRequestConfig.getGetBaseUserInfoUrl(), params);
        return JSON.parseObject(resultJson,BaseUserInfo.class);
    }

    public  String getAccessToken(){
        WeChatAccessToken token=ACCESS_TOKEN_MAP.get(ACCESS_TOKEN_KEY);
        if(token==null){
            return refreshAccessToken();
        }
        if(!token.isAvailable()){
            return refreshAccessToken();
        }
        return token.getAccess_token();
    }

    private synchronized String refreshAccessToken(){

        // 为了防止并发时，出现数据出错，因此请求之前，再进行一次判断
        WeChatAccessToken token=ACCESS_TOKEN_MAP.get(ACCESS_TOKEN_KEY);
        if(token!=null && token.isAvailable()){
            return token.getAccess_token();
        }

        Map<String,Object> paramMap=new HashMap<>();
        paramMap.put(DEFAULT_APP_ID_KEY, weChatAccessConfig.getAppId());
        paramMap.put(DEFAULT_SECRET_KEY, weChatAccessConfig.getSecret());
        String resultJson=HttpUtil.sendGet(weChatRequestConfig.getAccessTokenUrl(), paramMap);
        WeChatAccessToken accessToken= JSON.parseObject(resultJson, WeChatAccessToken.class);
        if(StringUtils.isNotEmpty(accessToken.getAccess_token())){
            ACCESS_TOKEN_MAP.put(ACCESS_TOKEN_KEY, accessToken);
            return accessToken.getAccess_token();
        }

        if(Objects.equals(accessToken.getErrcode(), -1)){
            // 微信服务器繁忙，再获取两次
            for(int i=0;i<2;i++){
                resultJson=HttpUtil.sendGet(weChatRequestConfig.getAccessTokenUrl(), paramMap);
                accessToken= JSON.parseObject(resultJson, WeChatAccessToken.class);
                if(StringUtils.isNotEmpty(accessToken.getAccess_token())){
                    ACCESS_TOKEN_MAP.put(ACCESS_TOKEN_KEY, accessToken);
                    return accessToken.getAccess_token();
                }
            }
            // 如果 请求两次还不成功，则把之前的移除掉
            ACCESS_TOKEN_MAP.remove(ACCESS_TOKEN_KEY);
        }

        LOGGER.error("获取微信accessToken失败，返回码:{}", accessToken.getErrcode());
        return null;
    }
}
